package jee.boot.module.authority.service;

import jee.boot.common.basic.CrudService;
import jee.boot.entity.system.Filter;
import jee.boot.common.standard.AuthorityHandler;
import jee.boot.common.utils.StringUtils;
import jee.boot.entity.auth.*;
import jee.boot.module.authority.dao.RoleDao;
import jee.boot.module.authority.dao.SbjAggrDao;
import jee.boot.module.authority.dao.SbjAuthDao;
import jee.boot.module.authority.dao.UserDao;
import jee.boot.entity.auth.AuthConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色
 */
@Service
public class RoleService extends CrudService<RoleDao, Role> {

    @Autowired
    private SbjAuthDao sbjAuthDao;
    @Autowired
    private SbjAggrDao sbjAggrDao;
    @Autowired
    private UserDao userDao;
    @Override
    public Role get(Role entity) {
        entity = super.get(entity);
        getMany(entity);

        return entity;
    }

    /**
     * 补充一堆多数据
     *
     * @param entity
     */
    public void getMany(Role entity) {
        // 根据主体ID查询所有原子权限
        List<SbjAuth> list = super.getOneToMany(sbjAuthDao, entity, new SbjAuth(), "sbj");
        if (list.size() > 0) {
            // 将列表中的原子权限筛选出来,填入到角色中
            entity.setAuthorityList(list.stream().map(d -> d.getAuthority()).collect(Collectors.toList()));
        }
        /**
         * DIC_AUTH_AuthSbjType_AST01	用户
         * DIC_AUTH_AuthSbjType_AST02	用户组
         * DIC_AUTH_AuthSbjType_AST03	角色
         * DIC_AUTH_AuthSbjType_AST99	其它
         */
        // 根据角色Id查询用户
        List<SbjAggr> objList = super.getOneToMany(sbjAggrDao, entity, new SbjAggr(), "obj");
        if (objList.size() > 0) {
            // 设置用户
            User user = new User();
            user.addFilter(new Filter("id", "in", getBasicSbjIdListByType(AuthConstant.AUTH_SBJ_TYPE_USER, objList)));
            entity.setUserList(userDao.findList(user));
        }
    }

    @Override
    public void save(Role entity) {
        //保存数据
        super.save(entity);
        List<SbjAuth> list = new ArrayList<>();
        // 保存所有的原子权限关联
        if (entity.getAuthorityList() != null) {
            for (Authority authority : entity.getAuthorityList()) {
                SbjAuth sbjAuth = new SbjAuth(authority);
                sbjAuth.setSbjType(AuthConstant.AUTH_SBJ_TYPE_ROLE);
                list.add(sbjAuth);
            }
        }
        // 插入关联数据
        if (list.size() > 0) {
            super.saveOneToMany(sbjAuthDao, entity, "sbj", list);
        }
    }

    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, allEntries = true)
    })
    @Override
    public void update(Role entity) {
        //更新数据
        super.update(entity);
        List<SbjAuth> list = new ArrayList<>();
        // 修改所有的原子权限关联
        if (entity.getAuthorityList() != null) {
            for (Authority authority : entity.getAuthorityList()) {
                SbjAuth sbjAuth = new SbjAuth(authority);
                sbjAuth.setSbjType(AuthConstant.AUTH_SBJ_TYPE_ROLE);
                list.add(sbjAuth);
            }
        }
        // 修改关联数据
        super.updateOneToMany(sbjAuthDao, entity, new SbjAuth(), "sbj", list);
    }

    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, allEntries = true)
    })
    @Override
    public void delete(Role entity) {
        // 删除角色
        super.delete(entity);
        // 删除与的关联关系
        super.deleteOneToMany(sbjAggrDao, entity, new SbjAuth(), "sbj");
    }
    /**
     * 根据关联表的数据按类型取出所有的权限主体entity的id
     *
     * @param type
     * @param list
     * @return
     */
    private List<String> getBasicSbjIdListByType(String type, List<SbjAggr> list) {
        return list.stream()
                .filter(d -> StringUtils.equals(type, d.getSbjType()))
                .map(d -> d.getSbj().getId())
                .collect(Collectors.toList());
    }
}
